import 'dart:collection';
import 'dart:convert';
import 'dart:io' show Platform;

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:opene/app_utils.dart';
import 'package:opene/net/response/base_response.dart';
import 'package:opene/net/response/response.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../app_constant.dart';
import '../login/login.dart';
import 'interceptor/custom_interceptor.dart';
import 'method/base_method.dart';
import 'package:http/http.dart' as http;

/// 网络管理
class NetworkManager {
  factory NetworkManager() => _getInstance();
  static NetworkManager _instance = NetworkManager._initialize();
  Dio _dio;

  static NetworkManager _getInstance() {
    _instance ??= NetworkManager._initialize();
    return _instance;
  }

  NetworkManager._initialize() {
    // 配置BaseOptions
    BaseOptions options = BaseOptions(
        baseUrl: Constants.baseUrl,
        //连接超时
        connectTimeout: const Duration(seconds: 15),
        //接收超时
        receiveTimeout: const Duration(seconds: 10),
        //内容类型
        contentType: 'application/json;Charset=UTF-8',
        //响应数据类型：Json
        responseType: ResponseType.json);
    _dio = Dio(options);
    //添加日志拦截器
    _dio.interceptors.add(CustomInterceptor());
  }

  ///网络请求
  Future<BaseResponse> request<T>(BuildContext context, String path, {BaseMethod method = BaseMethod.get, Map<String, dynamic> params, data, Options options}) async {
    const methodValues = {
      BaseMethod.get: 'get',
      BaseMethod.post: 'post',
      BaseMethod.put: 'put',
      BaseMethod.delete: 'delete',
      BaseMethod.patch: 'patch',
      BaseMethod.head: 'head',
    };
    Map<String, dynamic> headers = HashMap();

    try {
      SharedPreferences sp = await SharedPreferences.getInstance();

      if (Constants.tokenValue == null) {
        Constants.tokenValue = sp.getString(Constants.token);
        if (Constants.tokenValue != null) {
          headers["X-Access-Token"] = Constants.tokenValue;
        }
      } else {
        headers["X-Access-Token"] = Constants.tokenValue;
      }
      if (Constants.locationValue == null) {
        Constants.locationValue = sp.getString(Constants.location);
        if (Constants.locationValue != null) {
          headers["current-warehouse"] = Constants.locationValue;
        }
      } else {
        headers["current-warehouse"] = Constants.locationValue;
      }
    } catch (e) {
      e.printStackTrace();
    }

    try {
      PackageInfo packageInfo = await PackageInfo.fromPlatform();
      // headers["app-version"] = "2.0.0"; // 版本号
      headers["app-version"] = packageInfo.version; // 版本号
    } catch (e) {
      e.printStackTrace();
    }
    if (Platform.isIOS) {
      headers["User-Agent"] = "IOS";
    } else if (Platform.isAndroid) {
      headers["User-Agent"] = "Android";
    }

    options ??= Options(method: methodValues[method], headers: headers, responseType: ResponseType.json);

    try {
      Response response;
      // response = await _dio.request(path ,queryParameters: params, options: options);
      response = await _dio.request(path, data: data, queryParameters: params, options: options);
      // print("::::" + response.statusMessage);
      BaseResponse baseResponse = response.data;

      return BaseResponse.fromJson(baseResponse.data);
      // return response.data;
    } on DioException catch (e) {
      // print("e.message:"+e.message);
      // print(e.response.statusCode);
      // print("e.response.statusMessage:"+e.response.statusMessage);

      try {
        if (e.response != null) {
          // String json = jsonEncode(e.response.toString());
          // print("jsone:"+json);
          BaseResponse baseResponse = BaseResponse(code: e.response.statusCode, status: e.response.statusCode, msg: e.response.statusMessage, message: e.response.statusMessage);
          try {
            if (e.response.statusCode == 400) {
              Map<String, dynamic> articleM1 = json.decode(e.response.toString());
              baseResponse = BaseResponse.fromJson(articleM1);
            }
            if (e.response.statusCode == 404) {
              Map<String, dynamic> articleM1 = json.decode(e.response.toString());
              baseResponse = BaseResponse.fromJson(articleM1);
            }
          } catch (e) {
            e.printStackTrace();
          }

          if (baseResponse.code == 401) {
            if (context != null) {
              Utils.logOut();
              Navigator.pushAndRemoveUntil(
                context,
                MaterialPageRoute(builder: (context) => Login()),
                    (route) => route == null,
              );
            }
          }
          return baseResponse;
        }
        return BaseResponse(code: 0, status: 0, msg: "", message: "");
      } catch (e) {
        e.toString();
        return BaseResponse(code: 0, status: 0, msg: "", message: "");
      }
    }
  }

  ///网络请求
  Future<Response> requestUpload<T>(BuildContext context, String path, {BaseMethod method = BaseMethod.get, Map<String, dynamic> params, data, Options options}) async {
    const methodValues = {
      BaseMethod.get: 'get',
      BaseMethod.post: 'post',
      BaseMethod.put: 'put',
      BaseMethod.delete: 'delete',
      BaseMethod.patch: 'patch',
      BaseMethod.head: 'head',
    };
    Map<String, dynamic> headers = HashMap();

    try {

      headers["Transfer-Encoding"] = "chunked";
      // headers["Content-Type"] = "image/jpeg";
      headers["Content-Type"] = "application/octet-stream";
    } catch (e) {
      e.printStackTrace();
    }

    // options ??= Options(method: methodValues[method]);
    options ??= Options(method: methodValues[method], headers: headers);
    // options ??= Options(method: methodValues[method], headers: headers, contentType: "multipart/form-data");

    try {
      return await _dio.request(path, data: data, options: options);
    } on DioException catch (e) {
      throw e;
    }
  }


  Future<String> uploadBytes(String url,var bytes) async {
    final response = await http.put(
      Uri.parse(url),
      body: bytes,
      headers: {
        'Transfer-Encoding': 'chunked',
        'Content-Type': 'application/octet-stream', // 或者其他适合你数据的Content-Type
      },
    );

    print(response);
    if (response.statusCode == 200) {
      print('Upload successful');
      return "ok";
    } else {
      print('Upload failed: ${response.statusCode}');
      return response.body;
    }
  }
}
